function [ w_ih ,w_ho,o_s] = bp_net( data,out,hidden_dim,rate,limit)
  % bp_net: Short description
  %
  % Extended description

  [data_size,in_dim] = size(data);

  w_ih = rand(in_dim+1,hidden_dim);
  w_ho = rand(hidden_dim+1,1);

  for i=1:limit
    [w_ih,w_ho,o_s] = train( data,out,hidden_dim,rate,w_ih,w_ho );
  end

end  % bp_net

function [ w_ih ,w_ho, o_s ] = train( data,out,hidden_dim,rate,w_ih ,w_ho )
% train: Short description
%
% Extended description

[data_size,in_dim] = size(data);

% 计算隐藏层调用sigmoid前的值
h = [data,ones(data_size,1)] * w_ih;
% 计算隐藏层调用sigmoid后的值及导数
h_s = sigmoid(h);
h_sd = sigmoid(h,1);

% 计算结果层调用sigmoid前的值
o = [h_s,ones(data_size,1)] * w_ho;
% 计算结果层调用sigmoid后的值及导数
o_s = sigmoid(o);
o_sd = out + sigmoid(o,3);

d_w_ho = zeros(hidden_dim+1,1);
d_w_ih = zeros(in_dim+1,hidden_dim);
for i = 1:data_size
  % 计算结果层和隐藏层间权重的梯度
  d_w_ho+= o_sd(i) * [h_s(i,:),1]';
  % 计算隐藏层的导数
  d_o = o_sd(i) * w_ho(1:end-1,:)';
  % 计算隐藏层和输入层间权重的梯度
  d_w_ih+= [data(i,:),1]' * d_o .* h_sd(i,:);
end
w_ih += d_w_ih*rate;
w_ho += d_w_ho*rate;
end  % train
